通过 Security 登录功能实现
Security pom包引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> </dependencies>
|
WebSecurityConfig 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override protected void configure(HttpSecurity http) throws Exception {
String[] pathArray = new String[] {"/user/captcha/base64Code","/user/send/sms/verifyCode","/user/forget/password"}; http.cors(); http.csrf().disable(); http.authorizeRequests() .anyRequest().authenticated() .accessDecisionManager(accessDecisionManager()) .antMatchers(pathArray).permitAll() .anyRequest().authenticated();
http.formLogin() .loginProcessingUrl("/user/login") .successHandler(authSuccessHandler()) .failureHandler(failureHandler()) .permitAll();
http.logout() .logoutUrl("/logout") .deleteCookies("JSESSIONID") .invalidateHttpSession(true) .logoutSuccessHandler(logoutSuccessHandler()) .permitAll(); http.exceptionHandling() .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint()) .accessDeniedHandler(accessDeniedHandler()); } @Autowired private UserDetailsService userDetailsService;
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { System.out.println("configure"); auth.userDetailsService(userDetailsService); }
@Bean @Override protected AuthenticationManager authenticationManager() { System.out.println("authenticationManager"); return new UserAuthenticationManager(); }
@Bean AuthenticationSuccessHandler authSuccessHandler() { return new UserAuthenticationHandler(); }
@Bean AuthenticationFailureHandler failureHandler() { return new UserFailureHandler(); }
@Bean public AccessDecisionManager accessDecisionManager() { List<AccessDecisionVoter<?>> decisionVoters = Arrays.asList( new RoleVoter(), authorityVoter() ); return new UnanimousBased(decisionVoters); }
@Bean UserAccessDecisionVoter authorityVoter() { return new UserAccessDecisionVoter(); }
@Bean LogoutSuccessHandler logoutSuccessHandler() { return new UserLogoutSuccessHandler(); }
@Bean AccessDeniedHandler accessDeniedHandler() { return new UserAccessDeniedHandler(); }
|
UserDetailsService 用户查询服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Service public class UserDetailsServiceImpl implements UserDetailsService {
@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { System.out.println("loadUserByUsername"); return null; } }
|
UserAccessDecisionVoter 投票器
可以动态实现对请求地址的拦截
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class UserAccessDecisionVoter implements AccessDecisionVoter { @Override public boolean supports(ConfigAttribute attribute) { return true; }
@Override public int vote(Authentication authentication, Object object, Collection collection) { System.out.println("UserAccessDecisionVoter"); FilterInvocation fi = (FilterInvocation) object; System.out.println(fi.getRequestUrl()); return 1; }
@Override public boolean supports(Class clazz) { return clazz.equals(FilterInvocation.class); } }
|
UserAuthenticationManager 用户授权管理
对不同方式登录的用户授权,如快捷登录,扫码登录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class UserAuthenticationManager implements AuthenticationManager {
private static final Logger LOGGER = LoggerFactory.getLogger(UserAuthenticationManager.class); @Reference(version = "1.0") private UserService userService;
private final List<GrantedAuthority> AUTHORITIES = new ArrayList<>();
public UserAuthenticationManager() { AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER")); }
@Override public Authentication authenticate(Authentication auth) throws AuthenticationException {
if (check(auth)) { LOGGER.info("UserAuthenticationManager -->"); return new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), AUTHORITIES); } throw new BadCredentialsException("Bad Credentials"); } ... }
|
UserAuthenticationHandler 登录成功
1 2 3 4 5 6 7 8 9 10
| public class UserAuthenticationHandler extends SimpleUrlAuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request , HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.setCharacterEncoding("UTF-8"); System.out.println("onAuthenticationSuccess"); } }
|
UserFailureHandler 登录失败
对登录失败异常定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class UserFailureHandler extends SimpleUrlAuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response , AuthenticationException exception) throws IOException, ServletException { response.setCharacterEncoding("UTF-8"); logger.info("onAuthenticationFailure "+exception.getMessage(),exception);
if(exception instanceof BadCredentialsException){ String[] array = exception.getMessage().split("="); if(array.length>1){ JSON.writeJSONString(response.getWriter(), TeResponse.error(array[0],array[1])); return; } } JSON.writeJSONString(response.getWriter(), TeResponse.error(StateEnum.S_1004)); } }
|
UserLogoutSuccessHandler 退出成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class UserLogoutSuccessHandler implements LogoutSuccessHandler { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { SessionUtil.removeSessionAttribute(Const.LOGIN_SESSION_KEY, request); SecurityContextHolder.clearContext(); response.setCharacterEncoding("UTF-8"); JSON.writeJSONString(response.getWriter(), TeResponse.success()); } }
### UserAccessDeniedHandler 自定义权限不足 ```java public class UserAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { TeUser user = SessionUtil.getSessionAttribute(Const.LOGIN_SESSION_KEY, request); System.out.println("UserAccessDeniedHandler"); response.setCharacterEncoding("UTF-8"); if (null == user) { JSON.writeJSONString(response.getWriter(), TeResponse.error(StateEnum.S_401)); } else{ JSON.writeJSONString(response.getWriter(), TeResponse.error(StateEnum.S_403)); } } }
|
UserAccessDeniedHandler 认证用户无权限访问异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class UserAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { TeUser user = SessionUtil.getSessionAttribute(Const.LOGIN_SESSION_KEY, request); System.out.println("UserAccessDeniedHandler"); response.setCharacterEncoding("UTF-8"); if (null == user) { JSON.writeJSONString(response.getWriter(), TeResponse.error(StateEnum.S_401)); } else{ JSON.writeJSONString(response.getWriter(), TeResponse.error(StateEnum.S_403)); } } }
|
LoginUrlAuthenticationEntryPoint 未登录无权限访问异常
1 2 3 4 5 6 7 8 9 10 11
| public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { System.out.println("LoginUrlAuthenticationEntryPoint"); response.setContentType("application/json;charset=utf-8"); PrintWriter out = response.getWriter(); out.write(JsonUtil.toJSON(TeResponse.error(StateEnum.S_401))); out.flush(); out.close(); } }
|